'''
Created on Jun 14, 2010

@author: oabalbin
'''
import operator
import numpy as np
from collections import defaultdict, deque

from interactome.common.classes import interaction


def map_nodes_names2number(nodelist):
    """
    returns a dictionary with the nodes mapped to an integer, because that it is the input for the dhea 
    """
    nodelistDict=defaultdict()
    for indicator, node in enumerate(nodelist):
        nodelistDict[node] = indicator
    
    return nodelistDict


def write_edge_list_dhea_file(list_of_interactions, nodelistDict, outputfile_dhea, score):
    
    header = ["#nodeA","nodeB","score"]
    outputfile_dhea.write(",".join(header).replace(",","\t")+'\n')

    f = operator.attrgetter(score)
    for thisIntc in list_of_interactions:
        myscore_value = f(thisIntc)
        
        transcript = thisIntc.item_id_b.split('_') 
        if len(transcript) > 1:
            item_id_b = transcript[0]
            outline_dhea = [nodelistDict[thisIntc.item_id_a], nodelistDict[item_id_b]+'_mrna', myscore_value]
        else:
            outline_dhea = [nodelistDict[thisIntc.item_id_a], nodelistDict[thisIntc.item_id_b], myscore_value]
        
        #outline_dhea = [nodelistDict[thisIntc.item_id_a], nodelistDict[thisIntc.item_id_b], myscore_value]         
        outputfile_dhea.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')

def write_edge_list_cytoscape(list_of_interactions, map_prot2geneDict,outputfile_cytoscape, score):
    
    header = ["#nodeA","Interaction","nodeB","score"]
    outputfile_cytoscape.write(",".join(header).replace(",","\t")+'\n')
    
    f = operator.attrgetter(score)
    for thisIntc in list_of_interactions:
        myscore_value = f(thisIntc)
        
        #outline_cyt = [map_prot2geneDict[thisIntc.item_id_a], "PPI", map_prot2geneDict[thisIntc.item_id_b], myscore_value]        
        
        outline_cyt = [thisIntc.item_id_a, map_prot2geneDict[thisIntc.item_id_a], "PPI", thisIntc.item_id_b, map_prot2geneDict[thisIntc.item_id_b], myscore_value]
        
        outputfile_cytoscape.write(",".join(map(str,outline_cyt)).replace(',','\t')+'\n')


def write_nodes_list_dhea_file(nodelist,nodelistDict,outputfile, nodes_score):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    for  node in nodelist:
    #for node, indicator in nodelistDict.iteritems():
        if not nodes_score:
            myscore_value = np.random.uniform(low=0.0, high=1.0)
        
        outline_dhea = [nodelistDict[node], myscore_value]
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_node_list_number(nodelistDict, outputfile, map_prot2geneDict={}):
    
    for node, indicator in nodelistDict.iteritems(): 
        if map_prot2geneDict:
            outline = [map_prot2geneDict[node], node, indicator]
        else:
            outline = [node, indicator]
            
        outputfile.write(",".join(map(str,outline)).replace(',','\t')+'\n')


def get_protein_names_from_hugo(nodelistDict, map_prot2geneDict, genedict):
    """ 
    Returns the nodes that are in both the interactome and the gene list
    the dictionary gene indicator = value for that node 
    """
    selected_nodes=defaultdict()
    gene_notfound=[]
    for gene in genedict:
        try:
            node_indicator = map_prot2geneDict[gene]
            selected_nodes[node_indicator] = genedict[gene]
        except KeyError:
            gene_notfound.append(gene)
    
    return selected_nodes, gene_notfound


def write_nodes_list_dhea_file2(nodelist, protein2gene_table, protein_indicator, external_genes_dict, outputfile):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    notfound_weight=0.0
    #names_indexes = protein2gene_table.shape[0]
    for node in nodelist:
        
        gene_name_list = list(protein2gene_table[protein2gene_table[:,0] == node,1])
        
        indicator = protein_indicator[node]

        if not gene_name_list:
            outline_dhea = [indicator, notfound_weight]
            outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
            continue
        
        for gene_name in gene_name_list:             
            try:
                weight = external_genes_dict[gene_name]
                outline_dhea = [indicator, weight]
    
            except KeyError:
                outline_dhea = [indicator, notfound_weight]
        
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_nodes_list_dhea_file2names_deprecated(nodelist, protein2gene_table, protein_indicator, external_genes_dict, outputfile):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    notfound_weight=0.0
    #names_indexes = protein2gene_table.shape[0]
    for node in nodelist:
        
        gene_name_list = list(protein2gene_table[protein2gene_table[:,0] == node,1])
        nfg = 'gene_notfound'
        indicator = protein_indicator[node]

        if not gene_name_list:
            outline_dhea = [nfg+'('+str(indicator)+')', notfound_weight]
            outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
            continue
        
        for gene_name in gene_name_list:             
            try:
                weight = external_genes_dict[gene_name]
                outline_dhea = [gene_name+'('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [nfg+'('+str(indicator)+')', notfound_weight]
        
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')

def write_nodes_list_dhea_file2names(nodelist, protein2gene, protein_indicator, external_genes_dict, outputfile):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    notfound_weight=0.0
    #names_indexes = protein2gene_table.shape[0]
    outputfile.write('#node'+'\tweigth'+'\n')
    for node in nodelist:
            
        gene_name = protein2gene[node]
        nfg = 'gene_notfound'
        indicator = protein_indicator[node]

        if not gene_name:
            outline_dhea = [nfg+'('+str(indicator)+')', notfound_weight]
            outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
            continue
        else:
            try:
                weight = external_genes_dict[gene_name]
                outline_dhea = [gene_name+'('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [gene_name+'('+str(indicator)+')', notfound_weight]
        
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_nodes_list_dhea_file2names2(nodelist, protein2gene, protein_indicator, external_proteins_dict, external_transcripts_dict, outputfile):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    notfound_weight=0.0
    #names_indexes = protein2gene_table.shape[0]
    outputfile.write('#node'+'\tweigth'+'\n')
    for node in nodelist:
        
        transcript = node.split('_')
        
        if len(transcript) > 1:
            istranscript=True
            gene_name = protein2gene[transcript[0]]
        else:
            istranscript=False
            gene_name = protein2gene[node]
        
        nfg = 'gene_notfound'
        indicator = protein_indicator[node]

        if not gene_name:
            outline_dhea = [nfg+'('+str(indicator)+')', notfound_weight]
            outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
            continue
        elif not istranscript:
            try:
                weight = external_proteins_dict[gene_name]
                outline_dhea = [gene_name+'('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [gene_name+'('+str(indicator)+')', notfound_weight]
        else:
            try:
                weight = external_transcripts_dict[gene_name]
                outline_dhea = [gene_name+'_mrna('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [gene_name+'_mrna('+str(indicator)+')', notfound_weight]

        
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')




def write_edge_list_dhea_file2names(list_of_interactions, proteins_revIndex, nodelistDict, outputfile_dhea, score):
    
    header = ["#nodeA","nodeB","score"]
    outputfile_dhea.write(",".join(header).replace(",","\t")+'\n')

    f = operator.attrgetter(score)
    nfg = "gene_notfound"
    for thisIntc in list_of_interactions:
        myscore_value = f(thisIntc)
        
        ita, itb = proteins_revIndex[thisIntc.item_id_a], proteins_revIndex[thisIntc.item_id_b]
             
        if not ita and not itb:
            item_a, item_b = nfg+'('+str(nodelistDict[thisIntc.item_id_a])+')', nfg+'('+str(nodelistDict[thisIntc.item_id_b])+')'
        elif not ita:    
            item_a, item_b = nfg+'('+str(nodelistDict[thisIntc.item_id_a])+')', itb+'('+str(nodelistDict[thisIntc.item_id_b])+')'
        elif not itb:
            item_a, item_b = ita+'('+str(nodelistDict[thisIntc.item_id_a])+')', nfg+'('+str(nodelistDict[thisIntc.item_id_b])+')'
        else:
            item_a, item_b = ita+'('+str(nodelistDict[thisIntc.item_id_a])+')', itb+'('+str(nodelistDict[thisIntc.item_id_b])+')'

                
        outline_dhea = [item_a, item_b, myscore_value]
        #outline_dhea = [proteins_revIndex[thisIntc.item_id_a]+'('+str(nodelistDict[thisIntc.item_id_a])+')', proteins_revIndex[thisIntc.item_id_b]+'('+str(nodelistDict[thisIntc.item_id_b])+')', myscore_value]         
        outputfile_dhea.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_edge_list_dhea_file2names2(list_of_interactions, proteins_revIndex, nodelistDict, outputfile_dhea, score):
    
    header = ["#nodeA","nodeB","score"]
    outputfile_dhea.write(",".join(header).replace(",","\t")+'\n')

    f = operator.attrgetter(score)
    nfg = "gene_notfound"
    for thisIntc in list_of_interactions:
        myscore_value = f(thisIntc)
        
        ita = proteins_revIndex[thisIntc.item_id_a]
        
        istranscript = False 
        transcript = thisIntc.item_id_b.split('_') 
        
        if len(transcript) > 1:
            itb = proteins_revIndex[transcript[0]]
            istranscript = True
        else:
            itb = proteins_revIndex[thisIntc.item_id_b]       
        
        if not ita and not itb:
            item_a, item_b = nfg+'('+str(nodelistDict[thisIntc.item_id_a])+')', nfg+'('+str(nodelistDict[thisIntc.item_id_b])+')'
        elif not ita:    
            item_a, item_b = nfg+'('+str(nodelistDict[thisIntc.item_id_a])+')', itb+'('+str(nodelistDict[thisIntc.item_id_b])+')'
        elif not itb:
            item_a, item_b = ita+'('+str(nodelistDict[thisIntc.item_id_a])+')', nfg+'('+str(nodelistDict[thisIntc.item_id_b])+')'
        elif istranscript:
            item_a, item_b = ita+'('+str(nodelistDict[thisIntc.item_id_a])+')', itb+'_mrna('+str(nodelistDict[thisIntc.item_id_b])+')'
        else:
            item_a, item_b = ita+'('+str(nodelistDict[thisIntc.item_id_a])+')', itb+'('+str(nodelistDict[thisIntc.item_id_b])+')'

                
        outline_dhea = [item_a, item_b, myscore_value]
        #outline_dhea = [proteins_revIndex[thisIntc.item_id_a]+'('+str(nodelistDict[thisIntc.item_id_a])+')', proteins_revIndex[thisIntc.item_id_b]+'('+str(nodelistDict[thisIntc.item_id_b])+')', myscore_value]         
        outputfile_dhea.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_nodes_list_dhea_file2namesS8(nodelist, protein_indicator, external_proteins_dict, external_transcripts_dict, outputfile):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    notfound_weight=0.0
    #names_indexes = protein2gene_table.shape[0]
    outputfile.write('#node'+'\tweigth'+'\n')
    for node in nodelist:
        
        transcript = node.split('_')
        if len(transcript) > 1:
            istranscript=True
            gene_name = transcript[0]
        else:
            istranscript=False
            gene_name = node
        
        nfg = 'gene_notfound'
        indicator = protein_indicator[node]

        if not gene_name:
            outline_dhea = [nfg+'('+str(indicator)+')', notfound_weight]
            outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
            continue
        elif not istranscript:
            try:
                weight = external_proteins_dict[gene_name]
                outline_dhea = [gene_name+'('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [gene_name+'('+str(indicator)+')', notfound_weight]
        else:
            try:
                weight = external_transcripts_dict[gene_name]
                #outline_dhea = [gene_name+'_mrna('+str(indicator)+')', weight]
                outline_dhea = [node+'('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [node+'('+str(indicator)+')', notfound_weight]

        
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_edge_list_dhea_file2namesS8(list_of_interactions, nodelistDict, outputfile_dhea, score):
    
    header = ["#nodeA","nodeB","score"]
    outputfile_dhea.write(",".join(header).replace(",","\t")+'\n')

    f = operator.attrgetter(score)
    nfg = "gene_notfound"
    for thisIntc in list_of_interactions:
        myscore_value = f(thisIntc)
        
        ita, itb  = thisIntc.item_id_a_hugo, thisIntc.item_id_b_hugo
        
        if not ita and not itb:
            item_a, item_b = nfg+'('+str(nodelistDict[ita])+')', nfg+'('+str(nodelistDict[itb])+')'
        elif not ita:    
            item_a, item_b = nfg+'('+str(nodelistDict[ita])+')', itb+'('+str(nodelistDict[itb])+')'
        elif not itb:
            item_a, item_b = ita+'('+str(nodelistDict[ita])+')', nfg+'('+str(nodelistDict[itb])+')'
        else:
            item_a, item_b = ita+'('+str(nodelistDict[ita])+')', itb+'('+str(nodelistDict[itb])+')'

                
        outline_dhea = [item_a, item_b, myscore_value]
        outputfile_dhea.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
        


def write_nodes_list_dhea_file2names8(nodelist, protein2gene, protein_indicator, external_proteins_dict, external_transcripts_dict, outputfile):
    """
    writes a file for the node in the interactome
    #label score
    node score is a dictionary with the node number and the weigth for the node. 
    The weigth should be compute as in Huang and Frankel 2009.
    """
    notfound_weight=0.0
    #names_indexes = protein2gene_table.shape[0]
    outputfile.write('#node'+'\tweigth'+'\n')
    for node in nodelist:
        
        transcript = node.split('_')
        
        if len(transcript) > 1:
            istranscript=True
            gene_name = protein2gene[transcript[0]]
        else:
            istranscript=False
            gene_name = protein2gene[node]
        
        nfg = 'gene_notfound'
        indicator = protein_indicator[node]

        if not gene_name:
            outline_dhea = [nfg+'('+str(indicator)+')', notfound_weight]
            outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')
            continue
        elif not istranscript:
            try:
                weight = external_proteins_dict[gene_name]
                outline_dhea = [gene_name+'('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [gene_name+'('+str(indicator)+')', notfound_weight]
        else:
            try:
                weight = external_transcripts_dict[gene_name]
                outline_dhea = [gene_name+'_mrna('+str(indicator)+')', weight]
    
            except KeyError:
                outline_dhea = [gene_name+'_mrna('+str(indicator)+')', notfound_weight]

        
        outputfile.write(",".join(map(str,outline_dhea)).replace(',','\t')+'\n')


def write_node_list_numberS8(nodelistDict, outputfile, map_prot2geneDict={}):
    
    for node, indicator in nodelistDict.iteritems(): 
        node = node.split('_')[0]
        if map_prot2geneDict:
            outline = [map_prot2geneDict[node], node, indicator]
        else:
            outline = [node, indicator]
            
        outputfile.write(",".join(map(str,outline)).replace(',','\t')+'\n')




def dict_of_names(inputfile):
    """
    Reads a file with a list of hugo gene Names and an associated value
    """    
    genlist=defaultdict()
    for line in inputfile:        
        line = line.strip('\n')
        fields = line.split('\t')
        #print fields 
        # To skip headers, star reading samples in column 7 of the file
        if fields[0][0] == '#': 
            continue                             
        if fields[0]=='':
            continue
        
        genlist[fields[0]] = fields[1]
    
    return genlist


def list_of_names(inputfile):
        
        genlist=deque()
        for line in inputfile:        
            line = line.strip('\n')
            fields = line.split('\t')
            #print fields 
            # To skip headers, star reading samples in column 7 of the file
            if fields[0][0] == '#': 
                continue                             
            if fields[0]=='':
                continue
            genlist.append(fields[0])
        
        return genlist

